package mya_dc.client.gui;

import java.awt.Font;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.io.IOException;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

import mya_dc.client.core.ClientSettings;
import mya_dc.client.core.CompilationClient;
import mya_dc.client.gui.ProgressWindow.EActionType;
import mya_dc.client.gui.TextMessages.EMessageBoxType;
import mya_dc.shared_classes.MYA_FileTreeNode;
import mya_dc.shared_classes.MyaCompilationError;
import mya_dc.shared_classes.SharedDefinitions;
import mya_dc.shared_classes.MYA_FileTreeNode.FilesToGet;
import mya_dc.shared_classes.Message.EMessageType;
import mya_dc.shared_classes.gui.AboutWindow;
import mya_dc.shared_classes.gui.Java2Clipboard;
import mya_dc.shared_classes.gui.MultiLineCellRenderer;
import mya_dc.shared_classes.gui.MultiLineTable;
import com.swtdesigner.SwingResourceManager;

/**
 * The client's main window
 * 
 * @author      Adam Levi
 * <br>			MYA
 */
public class ClientMainWindow {
	
	//designer variables
	private JScrollPane scrollPane;
	private MultiLineTable 	errorsTable;
	private JMenuItem 		loadProjectMenuItem;
	private JFrame 			frame;
	private JTree		 	projectTree;
	private	JMenuItem 		saveProjectMenuItem;
	private JButton			saveProjectButton;
	private JLabel			statusLabel;
	
	/**
	 * Launch the application
	 * @param args
	 */
	public static void main(String args[]) {
		try {
			ClientMainWindow window = new ClientMainWindow();
			window.frame.setVisible(true);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Create the application
	 */
	public ClientMainWindow() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame
	 */
	private void initialize() {
		try 
		{
		UIManager.setLookAndFeel(
	    "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
		}
		catch(Exception e) { }

		frame = new JFrame();
		frame.addWindowFocusListener(new WindowFocusListener() {
			public void windowGainedFocus(final WindowEvent e) {
				doOnFocus();
			}
			public void windowLostFocus(final WindowEvent e) {
			}
		});
		frame.getContentPane().setBackground(SystemColor.control);
		frame.setResizable(false);
		frame.setTitle("MYA DC Client");
		frame.getContentPane().setLayout(null);
		frame.setBounds(100, 100, 370, 740);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		final JMenuBar menuBar = new JMenuBar();
		frame.setJMenuBar(menuBar);

		final JMenu fileMenu = new JMenu();
		fileMenu.setText("File");
		menuBar.add(fileMenu);

		final JMenuItem newProjectMenuItem = new JMenuItem();
		newProjectMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				doOpenNewProject();
			}
		});
		newProjectMenuItem.setText("New Project");
		fileMenu.add(newProjectMenuItem);

		saveProjectMenuItem = new JMenuItem();
		saveProjectMenuItem.setEnabled(false);
		saveProjectMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				saveProject(m_ProjectDataFile);
			}
		});
		saveProjectMenuItem.setText("Save Project");
		fileMenu.add(saveProjectMenuItem);

		loadProjectMenuItem = new JMenuItem();
		loadProjectMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				loadProject();
			}
		});
		loadProjectMenuItem.setText("Load Project");
		fileMenu.add(loadProjectMenuItem);

		final JMenu projectMenu = new JMenu();
		projectMenu.setText("Project");
		menuBar.add(projectMenu);

		final JMenuItem refreshProjectTreeMenuItem = new JMenuItem();
		refreshProjectTreeMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				doUpdateButton();
			}
		});
		refreshProjectTreeMenuItem.setText("Refresh Project Tree");
		projectMenu.add(refreshProjectTreeMenuItem);

		final JMenuItem copyErrorsListMenuItem = new JMenuItem();
		copyErrorsListMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				if (!isClientLoaded())
					return;
				Java2Clipboard.copyToClipboard(m_Client.getCompilationErrors().toString());
			}
		});
		copyErrorsListMenuItem.setText("Copy Errors List");
		projectMenu.add(copyErrorsListMenuItem);

		final JMenuItem openErrorsWindowMenuItem = new JMenuItem();
		openErrorsWindowMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				doOpenErrorsWindow();
			}
		});
		openErrorsWindowMenuItem.setText("Open Errors Window");
		projectMenu.add(openErrorsWindowMenuItem);

		projectMenu.addSeparator();

		final JMenuItem compileProjectMenuItem = new JMenuItem();
		compileProjectMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				doAction(EActionType.COMPILE_PROCCESS,FilesToGet.OUT_DATED_FILES);
			}
		});
		compileProjectMenuItem.setText("Compile Project");
		projectMenu.add(compileProjectMenuItem);

		final JMenuItem transferFilesMenuItem = new JMenuItem();
		transferFilesMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				doAction(EActionType.FILE_TRANSFER,FilesToGet.OUT_DATED_FILES);
			}
		});
		transferFilesMenuItem.setText("Transfer updated files");
		projectMenu.add(transferFilesMenuItem);

		final JMenuItem transferAllProjectMenuItem = new JMenuItem();
		transferAllProjectMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				if (!isClientLoaded())
					return;
				doAction(EActionType.FILE_TRANSFER, FilesToGet.ALL_FILES);
			}
		});
		transferAllProjectMenuItem.setToolTipText("Force transfer of all files");
		transferAllProjectMenuItem.setText("Transfer ALL project");
		projectMenu.add(transferAllProjectMenuItem);

		projectMenu.addSeparator();

		final JMenuItem openOutputFolderMenuItem = new JMenuItem();
		openOutputFolderMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				openOutputFolder();
			}
		});
		openOutputFolderMenuItem.setText("Open output folder");
		projectMenu.add(openOutputFolderMenuItem);

		final JMenuItem openProjectFolderMenuItem = new JMenuItem();
		openProjectFolderMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				if (!isClientLoaded())
					return;
				  try
				  {
					  Runtime.getRuntime().exec(
						  "explorer " + m_Client.getSettings().workingDirectory,null);
				  }
				  catch (IOException e1)
				  { 
				  }
			}
		});
		openProjectFolderMenuItem.setText("Open project folder");
		projectMenu.add(openProjectFolderMenuItem);

		projectMenu.addSeparator();

		final JMenuItem propertiesMenuItem = new JMenuItem();
		propertiesMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				openPropertiesWindow();
			}
		});
		propertiesMenuItem.setText("Properties");
		projectMenu.add(propertiesMenuItem);

		final JMenu helpMenu = new JMenu();
		helpMenu.setText("Help");
		menuBar.add(helpMenu);

		final JMenuItem helpMenuItem = new JMenuItem();
		helpMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				SharedDefinitions.openHelpFile(frame);
			}
		});
		helpMenuItem.setText("Help");
		helpMenu.add(helpMenuItem);

		final JMenuItem aboutMenuItem = new JMenuItem();
		aboutMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				AboutWindow.showAbout(frame);
			}
		});
		aboutMenuItem.setText("About");
		helpMenu.add(aboutMenuItem);

		final JToolBar toolBar = new JToolBar();
		toolBar.setBackground(SystemColor.inactiveCaptionText);
		toolBar.setBounds(-1, 0, 423, 27);
		frame.getContentPane().add(toolBar);

		saveProjectButton = new JButton();
		saveProjectButton.setBackground(SystemColor.inactiveCaptionText);
		saveProjectButton.setEnabled(false);
		saveProjectButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				saveProject(m_ProjectDataFile);
			}
		});
		saveProjectButton.setIcon(SwingResourceManager.getIcon("images/save_project_icon.png"));
		saveProjectButton.setToolTipText("Save Project");
		toolBar.add(saveProjectButton);

		final JButton loadProjectButton = new JButton();
		loadProjectButton.setBackground(SystemColor.inactiveCaptionText);
		loadProjectButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				loadProject();
			}
		});
		loadProjectButton.setIcon(SwingResourceManager.getIcon("images/load_project_icon.png"));
		loadProjectButton.setToolTipText("Load Project");
		toolBar.add(loadProjectButton);

		final JButton transferFilesbutton = new JButton();
		transferFilesbutton.setBackground(SystemColor.inactiveCaptionText);
		transferFilesbutton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				doAction(EActionType.FILE_TRANSFER, FilesToGet.OUT_DATED_FILES);
			}
		});
		transferFilesbutton.setToolTipText("Transfer Files to Server");
		toolBar.add(transferFilesbutton);
		transferFilesbutton.setIcon(SwingResourceManager.getIcon("images/transfer_files_icon.png"));

		statusLabel = new JLabel();
		statusLabel.setBorder(new TitledBorder(null, "", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
		statusLabel.setText("Idle");
		statusLabel.setBounds(9, 33, 344, 27);
		frame.getContentPane().add(statusLabel);
		
		final JPanel panel_1 = new JPanel();
		panel_1.setAutoscrolls(true);
		panel_1.setBackground(SystemColor.control);
		panel_1.setLayout(null);
		panel_1.setBorder(new TitledBorder(null, "", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
		panel_1.setBounds(10, 419, 344, 256);
		frame.getContentPane().add(panel_1);

		final JTabbedPane tabbedPane = new JTabbedPane();
		tabbedPane.addMouseListener(new MouseAdapter() {
			public void mouseClicked(final MouseEvent e) {
				doOpenErrorsWindow();
			}
		});
		tabbedPane.setBounds(10, 10, 334, 236);
		panel_1.add(tabbedPane);

		scrollPane = new JScrollPane();
		tabbedPane.addTab("Problems", null, scrollPane, null);

		errorsTable = new MultiLineTable();
		errorsTable.setShowGrid(true);
		errorsTable.addMouseListener(new MouseAdapter() {
			public void mouseClicked(final MouseEvent e) {
				if (e.getClickCount() < 2 || !isClientLoaded())
					return;
				doDoubleClickOnTable(errorsTable.rowAtPoint(e.getPoint()));
			}
		});
		scrollPane.setViewportView(errorsTable);

		final JButton refreshProjectTreeButton = new JButton();
		refreshProjectTreeButton.setBackground(SystemColor.inactiveCaptionText);
		refreshProjectTreeButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				doUpdateButton();
			}
		});
		toolBar.add(refreshProjectTreeButton);
		refreshProjectTreeButton.setToolTipText("Refresh Project Tree");
		refreshProjectTreeButton.setIcon(SwingResourceManager.getIcon("images/refrsh_icon.png"));

		final JButton propertiesButton = new JButton();
		propertiesButton.setBackground(SystemColor.inactiveCaptionText);
		propertiesButton.setToolTipText("Properties");
		propertiesButton.setIcon(SwingResourceManager.getIcon("images/properties_icon.png"));
		propertiesButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				openPropertiesWindow();
			}
		});
		toolBar.add(propertiesButton);

		final JButton compileButton = new JButton();
		compileButton.setToolTipText("Compile!");
		compileButton.setBackground(SystemColor.inactiveCaptionText);
		compileButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				doAction(EActionType.COMPILE_PROCCESS,FilesToGet.OUT_DATED_FILES);
			}
		});
		compileButton.setIcon(SwingResourceManager.getIcon("images/compile_icon.png"));
		toolBar.add(compileButton);
		
		final JScrollPane scrollPane_1 = new JScrollPane();
		scrollPane_1.setAutoscrolls(true);
		scrollPane_1.setBounds(10, 66, 344, 347);
		frame.getContentPane().add(scrollPane_1);
	
		projectTree = new JTree();
		projectTree.setFont(new Font("", Font.PLAIN, 14));
		scrollPane_1.setViewportView(projectTree);
		projectTree.addMouseListener(new MouseAdapter() {
			public void mouseClicked(final MouseEvent e) {
				if (e.getClickCount() < 2)
					return;
				TreePath path = projectTree.getClosestPathForLocation(e.getX(), e.getY());
				MYA_FileTreeNode node = m_Client.getProject().getChild(path);
				if (node == null || node.getFile().isDirectory())
					return;
				openFileOnEditor(
						node.getFile().getAbsolutePath(),
						-1,
						frame,
						m_Client.getSettings().editor,
						m_Client.getSettings().editorPath);
			}
		});
		
		//
		
		
		m_IsConnecting = false;
		updateModels();
	}
	
	/**
	 * set the status in statusLabel.
	 * 
	 * @param      status - the new status
	 */
	public void setStatusLabel(String status)
	{
		statusLabel.setText(status);
	}
	
	/**
	 * updates the project's tree and table tree UI
	 */
	public void updateModels()
	{
		if (m_Client == null)
		{
			projectTree.setModel(new DefaultTreeModel((new DefaultMutableTreeNode("--"))));
			projectTree.setRootVisible(false);
		}
		else
		{
			errorsTable.setModel(m_Client.getCompilationErrors());
			updateColumnToMultiline();
			projectTree.setModel(m_Client.getProject());
			projectTree.setRootVisible(true);
		}
		projectTree.updateUI();
		errorsTable.updateUI();	
	}
	
	public void doOnFocus()
	{
		if (m_Client == null)
			return;
		m_Client.getProject().updateTree();
		updateModels();
	}
	
	//variables
	private CompilationClient 	m_Client;
	private String				m_ProjectDataFile;
	private ProgressWindow 		m_TransferFilesWindow;
	private ErrorsWindow		m_ErrorsWindow;
	private boolean				m_IsConnecting;

	//methods
	
	/**
	 * updates the cells in the errors table to Multi-line cells
	 */
	private void updateColumnToMultiline()
	{
		MultiLineCellRenderer multiLineCR = new MultiLineCellRenderer();
		int n = errorsTable.getColumnCount();
		for (int i = 0; i < n; i++)
			errorsTable.getColumnModel().getColumn(i).setCellRenderer(multiLineCR);
		errorsTable.setAutoResizeMode(0);
		errorsTable.getColumnModel().getColumn(0).setPreferredWidth(25); //error number
		errorsTable.getColumnModel().getColumn(1).setPreferredWidth(75); //filename
		errorsTable.getColumnModel().getColumn(2).setPreferredWidth(25); //line number
		int width = scrollPane.getWidth() - 110;
		errorsTable.getColumnModel().getColumn(3).setPreferredWidth(width); //line number
	}
	
	/**
	 * opens the NewProjectWizard dialog
	 */
	private void doOpenNewProject()
	{
		NewProjectWizard pw = new NewProjectWizard();
		pw.setModal(true);
		CompilationClient tmp = pw.getProject();
		if (tmp != null)
		{
			saveProjectMenuItem.setEnabled(true);
			saveProjectButton.setEnabled(true);
			if (m_Client != null)
			{
				m_Client.closeConnection();
				m_Client = null;
			}
			m_Client = tmp;
			frame.setTitle("MYA DC Client - " + m_Client.getSettings().projectName);
			updateModels();
			closeProgressWindow();
			if (m_Client.getSettings().autoTransferFiles)
				doAction(EActionType.FILE_TRANSFER,FilesToGet.OUT_DATED_FILES);
		}	
	}
	
	/**
	 * opens the Errors Window
	 */
	private void doOpenErrorsWindow()
	{
		if (!isClientLoaded())
			return;
		if (m_ErrorsWindow == null)
		{
			m_ErrorsWindow = new ErrorsWindow();
		}
		m_ErrorsWindow.doUpdateTable(m_Client.getCompilationErrors(), m_Client.getSettings());
		m_ErrorsWindow.setVisible(true);
	}
	
	/**
	 * updates the client's tree view
	 */
	private void doUpdateButton()
	{
		if (!isClientLoaded())
			return;
		m_Client.getProject().updateTree();
		updateModels();
	}
	
	/**
	 * opens the file in the chosen editor according to the error
	 * 
	 * @param rowIndex - the number of the row that was clicked.
	 */
	private void doDoubleClickOnTable(int rowIndex)
	{
		if (rowIndex >= errorsTable.getRowCount() || m_Client == null)
			return;
		Object[] arr = m_Client.getCompilationErrors().toArray();
		MyaCompilationError error = (MyaCompilationError)arr[rowIndex];
		if (error.m_strFileName == null || error.m_strFileName.equals(""))
			return;
		int line = -1;
		try
		{
			line = Integer.parseInt(error.m_strLineNum);
		}
		catch(NumberFormatException e) { }
		openFileOnEditor(
				error.m_strFileName,
				line,
				frame,
				m_Client.getSettings().editor,
				m_Client.getSettings().editorPath);
	}
	
	/**
	 * opens the authentication window
	 * 
	 * @param message - the message the user will see in the dialog
	 */
	private boolean openAuthenticationWindows(String message)
	{
		Boolean result = new Boolean(false);
		AuthenticationDialog ad = new AuthenticationDialog(
				message,
				m_Client.getSettings(),
				result);
		ad.setModal(true);
		ad.setVisible(true);
		return (ad.isCanceled()==false);
	}
	
	/**
	 * handles transferring of files and compiling on server
	 * 
	 * @param action - the action to do (compilation or transfer files)
	 * @param typeOfFiles - the type of files that will be send
	 */
	private void doAction(final EActionType action, final FilesToGet typeOfFiles)
	{
		if (!isClientLoaded())
			return;
		if (m_IsConnecting)
		{
			TextMessages.showMessageBox(
					EMessageBoxType.ERROR_IS_CONNECTING,
					this.frame);
			return;	
		}
		m_IsConnecting = true;
		if ((m_Client.isConnected()==false))
			setStatusLabel(TextMessages.statusString_CONNECTING);
		
		if (!m_Client.getSettings().savePassword)
			if (openAuthenticationWindows("No password found, Enter Password")==false)
			{
				setStatusLabel(TextMessages.statusString_CANCELED);
				return; //canceled
			}
		SwingWorker<EMessageType, Void> connectWorker = new SwingWorker<EMessageType, Void>()
		{
		    @Override
		    public EMessageType doInBackground()
		    {
		    	if (m_Client.isConnected()==false)
		    		return m_Client.connect();
		    	return EMessageType.SUCCESS;
			}
		    @Override
		    public void done()
		    {
		    	try
		    	{
			    	switch(this.get())
			    	{
			    		case SUCCESS: 
			    			{
			    				setStatusLabel(TextMessages.statusString_CONNECTED);
			    				saveProjectIfNeeded();
			    				openTransferWindow();
								m_TransferFilesWindow.doAction(action,typeOfFiles,m_Client);
								break;
			    			}
			    		case LOGIN_EXISTING:
				    		{
			    				setStatusLabel(TextMessages.statusString_LOGIN_EXISTING);
		    					TextMessages.showMessageBox(EMessageBoxType.ERROR_UNABLE_TO_CONNECT,frame);
			    				break;
				    		}
			    		case LOGIN_FAILED_AUTHENTICATION_FAILED:
			    			{
			    				setStatusLabel(TextMessages.statusString_LOGIN_FAILED_AUTHENTICATION_FAILED);
			    				if (openAuthenticationWindows("Authentication Failed, Verifiy login details:")==false)
			    					break;
			    				m_IsConnecting = false;
			    				doAction(action,typeOfFiles);
			    				break;
			    			}
			    		case LOGIN_FAILED_SERVER_DISCONNECTED:
				    		{
				    			setStatusLabel(TextMessages.statusString_LOGIN_FAILED_SERVER_DISCONNECTED);
		    					TextMessages.showMessageBox(EMessageBoxType.ERROR_UNABLE_TO_CONNECT,frame);
				    			break;
				    		}
			    		case LOGIN_CONNECTION_TO_ALL_SERVERS_FAILED:
				    		{
			    				setStatusLabel(TextMessages.statusString_LOGIN_FAILED_NO_MORE_SERVERS);
		    					TextMessages.showMessageBox(EMessageBoxType.ERROR_UNABLE_TO_CONNECT,frame);
		    					break;
				    		}
				    	case ERROR_MASTER_SERVER_CONNECTION_FAILED:
					    	{
					    		setStatusLabel(TextMessages.statusString_ERROR_MASTER_SERVER_CONNECTION_FAILED);
		    					TextMessages.showMessageBox(EMessageBoxType.ERROR_UNABLE_TO_CONNECT,frame);
		    					break;
					    	}
			    		default:
			    			{
			    			setStatusLabel(TextMessages.statusString_CONNECTIION_ERROR);
		    					TextMessages.showMessageBox(EMessageBoxType.ERROR_UNABLE_TO_CONNECT,frame);
			    			}
			    	}

		    	}
		    	catch (Exception e) { }
		    	m_IsConnecting = false;
		    	if (!m_Client.getSettings().savePassword)
		    		m_Client.getSettings().password = "";
		    }

		};
	    connectWorker.execute();
	}
	
	/**
	 * checks if the project should be saved according to isNeedSaveToFile()
	 * function. if the project should be saved, a dialog will pop
	 * and it will ask the user if it want to save the project.
	 * 
	 * @see CompilationClient.isNeedSaveToFile()
	 */
	private void saveProjectIfNeeded()
	{
		//checks if the project should be saved
		if (!m_Client.isNeedSaveToFile())
			return;
		
		//asks user if he wants to save 
		int userAnswer = JOptionPane.showConfirmDialog(
		frame,
		"Connection Succeded, save project to file?",
		"Save dialog",0,3);
		if (userAnswer == 1)
			return;
		
		//open save file dialog
		saveProject(m_ProjectDataFile);
	}
	
	/**
	 * @return true if the client is loaded, otherwise show a message box
	 * that informs that no client is loaded and return false;
	 */
	private boolean isClientLoaded()
	{
		if (m_Client == null)
		{
			TextMessages.showMessageBox(EMessageBoxType.ERROR_NO_PROJECT,frame);
			return false;
		}
		return true;
	}
	
	/**
	 * opens a file on the chosen editor in a specified line
	 * @param filename	 - the path to the file
	 * @param lineNumber - the line number requested (-1 if no specific line requested)
	 * @param frame 	 - the frame that invoked the function
	 * @param editor 	 - the chosen editor
	 * @param editorPath - the location of the specified editor
	 */
	public static void openFileOnEditor(
			String filename,
			int lineNumber,
			JFrame frame,
			ClientSettings.EEditors editor,
			String editorPath
			)
	{
		//open editor for editing
		String launchString = null;
		switch(editor)
		{
			case NOTEPAD_PLUS_PLUS:
			{
				launchString = editorPath + " " +
				(lineNumber != -1 ? "-n" + Integer.toString(lineNumber) + " " : "") + 
				"\"" + filename + "\"";
				break;
			}
			case NOTEPAD_WINDOWS:
			case MICROSOFT_VISUAL_STUDIO:
			{
				launchString = editorPath + " " + "\"" + filename + "\"";
				break;
			}
		}
		if (launchString == null)
		{
			TextMessages.showMessageBox(EMessageBoxType.ERROR_LOADING_EDITOR,frame);
			return;
		}
		try
		{
			Runtime.getRuntime().exec(launchString, null);
		}
		catch (IOException e1)
		{ TextMessages.showMessageBox(EMessageBoxType.ERROR_LOADING_EDITOR,frame); }	
	}
	
	/**
	 * opens the properties window
	 */
	private void openPropertiesWindow()
	{
		if (!isClientLoaded())
			return;
		PropertiesWindow pw = new PropertiesWindow(m_Client.getSettings());
		pw.setModal(true);
		pw.setVisible(true);
	}
	
	/**
	 * closes the progress window
	 */
	private void closeProgressWindow()
	{
		if (m_TransferFilesWindow != null)
			m_TransferFilesWindow.forceClose();
	}
	
	/**
	 * opens the transfer window
	 */
	private void openTransferWindow()
	{
		if (m_TransferFilesWindow == null)
			m_TransferFilesWindow = new ProgressWindow(this); //0=Transfer
		m_TransferFilesWindow.setVisible(true);
	}
	private enum EFileChooser { SAVE, LOAD };
	
	/**
	 * loads a new project
	 */
	private void loadProject()
	{
		String projectLocation = openFileDialog(EFileChooser.LOAD);
		if (projectLocation == null)
			return;
		if (m_Client == null)
			m_Client = new CompilationClient();
		if (m_Client.loadData(projectLocation) == -1)
		{
			TextMessages.showMessageBox(EMessageBoxType.ERROR_UNABLE_TO_LOAD_PROJECT,frame);
			m_Client = null;
			return;
		}
		updateModels();
		closeProgressWindow();
		m_ProjectDataFile = projectLocation;
		saveProjectMenuItem.setEnabled(true);
		saveProjectButton.setEnabled(true);
		frame.setTitle("MYA Client - " + m_Client.getSettings().projectName);

	}
	
	/**
	 * saves a project
	 * @param location - the path where to save the project
	 */
	private void saveProject(String location)
	{
		String projectLocation = (location == null ? openFileDialog(EFileChooser.SAVE)
				: location);
		if (projectLocation == null)
			return;

		//add extension if needed
		int dotPos = projectLocation.lastIndexOf(".");
		if (dotPos == -1)
		{
			projectLocation += ".mya";
		}
		else
		{
			String extension = projectLocation.substring(dotPos+1);
			if (!(extension.equals("mya")))
			{
				projectLocation += ".mya";
			}
		}	
		
		//save data
		if (m_Client.saveData(projectLocation) == -1)
			TextMessages.showMessageBox(EMessageBoxType.ERROR_UNABLE_TO_SAVE_PROJECT,frame);
		m_ProjectDataFile = projectLocation;
	}
	
	/**
	 * opens a JFileChooser dialog
	 * 
	 * @param type - the type of files we want to choose
	 * 
	 * @return the path that was chosen, null if none was chosen
	 */
	private String openFileDialog(EFileChooser type)
	{
		JFileChooser fc = new JFileChooser();
		fc.setApproveButtonText( type == EFileChooser.SAVE ? "Save" : "Load");
		fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
		FileNameExtensionFilter filter = new FileNameExtensionFilter("MYA Project File","mya");
		fc.setFileFilter(filter);
		if (fc.showOpenDialog(frame)==JFileChooser.APPROVE_OPTION)
			return fc.getSelectedFile().getAbsolutePath();
		return null;
	}
	
	/**
	 * runs the project executable
	 */
	private void openOutputFolder()
	{
		if (!isClientLoaded())
			return;
		  try
		  {
			  Runtime.getRuntime().exec(
				  "explorer " + m_Client.getSettings().outputDirectory,null);
		  }
		  catch (IOException e1)
		  { 
		  }
		
	}
}

